
local ModeName = ...
local _M = {}
local _m = {}



local private = {}

--  获取数字类型的键并转为字符串
--  (注: 为 private.getTableStr的内部函数)
function private.getNumberKeyV (k, v)
    if type(v) == "string" 
    then 
        v = '"' .. v .. '"'
    elseif type(v) == "table"
    then
        v = private.getTableStr(v)
    end
    
    return "[" .. k .. "]:" .. v
  end

--  获取字符类型的键并转为字符串
--  (注: 为 private.getTableStr的内部函数)
function private.getStringKeyV (k, v)
    if type(v) == "string"
    then
        v = '"' .. v .. '"'
    elseif type(v) == "table"
    then
        v = private.getTableStr(v)
    end
    
    return '"' .. k .. '":' .. v
  end

--  表转为字符串  
--  return: string
function private.getTableStr (t)
    local str = ""
    
    for k, v in pairs(t)
    do
        if type(k) == "number" 
        then
            str = str  
                .. private.getNumberKeyV(k, v)
                .. ","
        elseif type(k) == "string"
        then
            str = str
                .. private.getStringKeyV(k, v)
                .. ","
        end
    end
    str = string.sub(str, 1, string.len(str) - 1)
    
    return "{" .. str .. "}"
  end

--  字符串转换字节数组 , 十进制  
--  return: array
function private.String_ByteArray (str)
    local byteArray = {}
    
    for i = 1, string.len(str)
    do
        byteArray[i] = string.byte(str, i)
    end
    
    return byteArray
  end

--  字节数组转换字符串  
--  return: string
function private.ByteArray_String (array)
    local str = ""
    for i = 1, #array
    do
        str = str .. string.char(array[i])
    end
    
    return str
  end

--  增加空符并换行
-- (注: 为 private.formatString 的内部函数)
local indent_true =function (exp, str_array)
    for i = 1, exp.indent_n
    do
        table.insert(str_array, exp.i + 1, 32)
    end
            
    table.insert(str_array, exp.i + 1, 10)
            
    exp.i = exp.i + 1 + exp.indent_n
    exp.len = exp.len + 1 + exp.indent_n
  end

--  减少空符并换行
-- (注: 为 private.formatString 的内部函数)
local indent_false =function (exp, str_array)
    local i = exp.indent_n
    while i <= exp.indent_n and i > 0
    do
        table.insert(str_array, exp.i, 32)
        
        if i == 0 then i = nil else i = i - 1 end
    end
    
    table.insert(str_array, exp.i, 10)
    
    exp.i = exp.i + 1 + exp.indent_n
    exp.len = exp.len + 1 + exp.indent_n
  end

--  格式化字符串  return: string
function private.formatString (t)
    local str = private.getTableStr(t)
    str_array = private.String_ByteArray(str)
    
    local exp = {}
    exp.i = 0
    exp.indent_n = 0
    exp.len = #str_array
    repeat
        exp.i = exp.i + 1
        --  遇到 ' { '(字节数123)则换行并缩进
        if str_array[exp.i] == 123
        then
            exp.indent_n = exp.indent_n + 1
            indent_true(exp, str_array)
        --  遇到 ' , '(字节数44)则换行并缩进
        elseif str_array[exp.i] == 44
        then
            indent_true(exp, str_array)
        --  遇到 ' } '(字节数125)则换行并缩进
        elseif str_array[exp.i - 1] ~= 10
          and  str_array[exp.i - 1] ~= 32
          and str_array[exp.i] == 125
        then
            exp.indent_n = exp.indent_n - 1
            indent_false(exp, str_array)
        end
    until(exp.i == exp.len)
    
    return private.ByteArray_String(str_array)
  end
--[[ ----------------------
  MethodName: println
  Value: { v: data[, "P" or "S"] }
  序列化表， "P":打印， "S": 返回字符串
]]-- ----------------------
function _M:println (v, ...)
    local variable = {...}
    
    if type(v) == "table" 
    then
        v = private.formatString(v)
    end
    
    if not(variable[1]) or variable[1] == "P"
        then    print(v)
    elseif variable[1] == "S"
        then    return v
    end
  end



-- 设置为只读表 ------------------------------------------------

_m.__index = _M

_m.__newindex = function (t, k, v)
    error("attempt to update a read-only table", 2)
end

_G[ModeName] = setmetatable({}, _m)

-- -----------------------------------------------------------

-- 向全局添加方法
function _G.println (v, ...)
    local formatable = _G[ModeName]:println(v, ...)
    if formatable
    then
      return formatable
    end
  end

return _G[ModeName]
